<template>
  <div class="audio-management">
    <div class="header">
      <h2>音频管理</h2>
      <el-button type="primary" @click="handleAdd">上传音频</el-button>
    </div>

    <el-card class="search-card">
      <el-form :inline="true" :model="searchForm" class="search-form">
        <el-form-item label="文件名">
          <el-input v-model="searchForm.filename" placeholder="请输入文件名" clearable />
        </el-form-item>
        <el-form-item label="类型">
          <el-select v-model="searchForm.type" placeholder="请选择类型" clearable>
            <el-option label="单词发音" value="word" />
            <el-option label="听力材料" value="listening" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <el-card class="table-card">
      <el-table
        v-loading="loading"
        :data="audioList"
        border
        style="width: 100%"
      >
        <el-table-column prop="id" label="ID" width="80" />
        <el-table-column prop="filename" label="文件名" />
        <el-table-column prop="type" label="类型" width="100">
          <template #default="{ row }">
            <el-tag :type="row.type === 'word' ? 'success' : 'warning'">
              {{ row.type === 'word' ? '单词发音' : '听力材料' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="size" label="大小" width="120">
          <template #default="{ row }">
            {{ formatFileSize(row.size) }}
          </template>
        </el-table-column>
        <el-table-column prop="duration" label="时长" width="100">
          <template #default="{ row }">
            {{ formatDuration(row.duration) }}
          </template>
        </el-table-column>
        <el-table-column prop="createdAt" label="上传时间" width="180">
          <template #default="{ row }">
            {{ new Date(row.createdAt).toLocaleString() }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="250">
          <template #default="{ row }">
            <el-button-group>
              <el-button type="primary" size="small" @click="handlePlay(row)">
                播放
              </el-button>
              <el-button type="success" size="small" @click="handleDownload(row)">
                下载
              </el-button>
              <el-button type="danger" size="small" @click="handleDelete(row)">
                删除
              </el-button>
            </el-button-group>
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination">
        <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :total="total"
          :page-sizes="[10, 20, 50, 100]"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </el-card>

    <!-- 音频上传对话框 -->
    <el-dialog
      v-model="dialogVisible"
      title="上传音频"
      width="500px"
    >
      <el-form
        ref="formRef"
        :model="audioForm"
        :rules="rules"
        label-width="80px"
      >
        <el-form-item label="音频文件" prop="file">
          <el-upload
            class="upload-demo"
            drag
            action="/api/audio/upload"
            :headers="uploadHeaders"
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            :before-upload="beforeUpload"
            accept="audio/*"
          >
            <el-icon class="el-icon--upload"><upload-filled /></el-icon>
            <div class="el-upload__text">
              将文件拖到此处，或<em>点击上传</em>
            </div>
            <template #tip>
              <div class="el-upload__tip">
                支持 mp3、wav 格式，且不超过 10MB
              </div>
            </template>
          </el-upload>
        </el-form-item>
        <el-form-item label="类型" prop="type">
          <el-select v-model="audioForm.type" placeholder="请选择类型">
            <el-option label="单词发音" value="word" />
            <el-option label="听力材料" value="listening" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 音频播放器 -->
    <el-dialog
      v-model="playerVisible"
      title="音频播放"
      width="400px"
      :close-on-click-modal="false"
    >
      <div class="audio-player">
        <audio
          ref="audioPlayer"
          :src="currentAudio?.url"
          controls
          class="audio-element"
        ></audio>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import request from '@/utils/request'
import { useUserStore } from '@/stores/user'

const userStore = useUserStore()

interface Audio {
  id: number
  filename: string
  type: 'word' | 'listening'
  size: number
  duration: number
  url: string
  createdAt: string
}

interface SearchForm {
  filename: string
  type: string
}

interface AudioForm {
  file: File | null
  type: string
}

// 数据列表
const audioList = ref<Audio[]>([])
const loading = ref(false)
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)

// 搜索表单
const searchForm = reactive<SearchForm>({
  filename: '',
  type: ''
})

// 音频表单
const dialogVisible = ref(false)
const formRef = ref<FormInstance>()
const audioForm = reactive<AudioForm>({
  file: null,
  type: 'word'
})

// 音频播放器
const playerVisible = ref(false)
const audioPlayer = ref<HTMLAudioElement>()
const currentAudio = ref<Audio>()

// 上传请求头
const uploadHeaders = {
  Authorization: `Bearer ${userStore.token}`
}

// 表单验证规则
const rules = {
  file: [
    { required: true, message: '请选择音频文件', trigger: 'change' }
  ],
  type: [
    { required: true, message: '请选择音频类型', trigger: 'change' }
  ]
}

// 格式化文件大小
const formatFileSize = (size: number) => {
  if (size < 1024) {
    return size + ' B'
  } else if (size < 1024 * 1024) {
    return (size / 1024).toFixed(2) + ' KB'
  } else {
    return (size / (1024 * 1024)).toFixed(2) + ' MB'
  }
}

// 格式化时长
const formatDuration = (duration: number) => {
  const minutes = Math.floor(duration / 60)
  const seconds = Math.floor(duration % 60)
  return `${minutes}:${seconds.toString().padStart(2, '0')}`
}

// 获取音频列表
const fetchAudioList = async () => {
  loading.value = true
  try {
    const params = {
      page: currentPage.value,
      pageSize: pageSize.value,
      ...searchForm
    }
    const { data } = await request('/api/audio', {
      method: 'GET',
      params
    })
    audioList.value = data.items
    total.value = data.total
  } catch (error) {
    console.error('获取音频列表失败:', error)
  } finally {
    loading.value = false
  }
}

// 搜索
const handleSearch = () => {
  currentPage.value = 1
  fetchAudioList()
}

// 重置搜索
const resetSearch = () => {
  searchForm.filename = ''
  searchForm.type = ''
  handleSearch()
}

// 分页
const handleSizeChange = (val: number) => {
  pageSize.value = val
  fetchAudioList()
}

const handleCurrentChange = (val: number) => {
  currentPage.value = val
  fetchAudioList()
}

// 新增音频
const handleAdd = () => {
  audioForm.file = null
  audioForm.type = 'word'
  dialogVisible.value = true
}

// 播放音频
const handlePlay = (row: Audio) => {
  currentAudio.value = row
  playerVisible.value = true
  // 等待 DOM 更新后播放
  setTimeout(() => {
    audioPlayer.value?.play()
  }, 100)
}

// 下载音频
const handleDownload = async (row: Audio) => {
  try {
    const response = await fetch(row.url)
    const blob = await response.blob()
    const url = window.URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = row.filename
    document.body.appendChild(a)
    a.click()
    window.URL.revokeObjectURL(url)
    document.body.removeChild(a)
  } catch (error) {
    console.error('下载音频失败:', error)
    ElMessage.error('下载失败')
  }
}

// 删除音频
const handleDelete = async (row: Audio) => {
  try {
    await ElMessageBox.confirm('确定要删除该音频吗？', '提示', {
      type: 'warning'
    })
    await request(`/api/audio/${row.id}`, {
      method: 'DELETE'
    })
    ElMessage.success('删除成功')
    fetchAudioList()
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除音频失败:', error)
    }
  }
}

// 上传前检查
const beforeUpload = (file: File) => {
  const isAudio = file.type.startsWith('audio/')
  const isLt10M = file.size / 1024 / 1024 < 10

  if (!isAudio) {
    ElMessage.error('只能上传音频文件！')
    return false
  }
  if (!isLt10M) {
    ElMessage.error('文件大小不能超过 10MB！')
    return false
  }

  audioForm.file = file
  return false // 阻止自动上传
}

// 上传成功
const handleUploadSuccess = (response: any) => {
  ElMessage.success('上传成功')
  dialogVisible.value = false
  fetchAudioList()
}

// 上传失败
const handleUploadError = () => {
  ElMessage.error('上传失败')
}

// 提交表单
const handleSubmit = async () => {
  if (!formRef.value) return
  
  await formRef.value.validate(async (valid) => {
    if (valid && audioForm.file) {
      const formData = new FormData()
      formData.append('file', audioForm.file)
      formData.append('type', audioForm.type)

      try {
        await request('/api/audio/upload', {
          method: 'POST',
          data: formData,
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        })
        ElMessage.success('上传成功')
        dialogVisible.value = false
        fetchAudioList()
      } catch (error) {
        console.error('上传失败:', error)
      }
    }
  })
}

onMounted(() => {
  fetchAudioList()
})
</script>

<style scoped>
.audio-management {
  padding: 20px;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.search-card {
  margin-bottom: 20px;
}

.search-form {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.table-card {
  margin-bottom: 20px;
}

.pagination {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.audio-player {
  display: flex;
  justify-content: center;
  padding: 20px 0;
}

.audio-element {
  width: 100%;
}

:deep(.el-upload-dragger) {
  width: 100%;
}
</style> 